package profile

import (
	"context"
	"encoding/json"
	"strconv"
	"strings"

	"mall/common/cachex"
	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	utilx "mall/common/utils/user"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/rpc/forumclient"
	"mall/service/user/rpc/userclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserProfileLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetUserProfileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserProfileLogic {
	return &GetUserProfileLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetUserProfileLogic) GetUserProfile(
	req *types.GetUserProfileReq,
	headers *[]*types.Header,
) (*types.UserProfileResp, error) {
	userId := jwt.GetUserId(l.ctx)

	var id uint64
	if req.UserId != nil && *req.UserId > 0 {
		id = *req.UserId
	} else if userId > 0 {
		id = userId
	}

	if id > 0 {
		var platform string
		if req.AuthType == nil || len(strings.TrimSpace(*req.AuthType)) == 0 {
			platform = globalkey.UserAuthTypeWechatMini
		} else {
			platform = *req.AuthType
		}
		platformId := utilx.GetThirdPartyPlatformId(platform)
		if platformId == 0 {
			return nil, resultx.NewErrCode(resultx.USER_AUTH_PARAM_INVALID)
		}

		// preload := "user:Id;userMeta:likeCount,collectEntryCount,collectEntryStatus,collectEntryItems,postPhotoCount,photoNewStatus,photoPostItems"
		// preload += ",orderCount,orderNewStatus,reviewCount,reviewNewStatus,askedQuestionCount,askedQuestionNewStatus"
		// preload += ",answeredQuestionCount,answeredQuestionNewStatus"
		preload := "user:Id;userMeta:wantEntryCount,ownEntryCount,ownEntryItems,ownEntryStatus,couponCount,expiringCouponCount"
		var eagerLoad string = "user:userMeta"
		res, err := l.svcCtx.UserRpc.GetUserProfile(l.ctx, &userclient.GetProfileReq{
			UserId:     pointy.GetPointer(id),
			Preload:    pointy.GetPointer(preload),
			EagerLoad:  pointy.GetPointer(eagerLoad),
			VisitorId:  pointy.GetPointer(userId),
			PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
		})
		if err != nil {
			return nil, err
		}

		if res == nil || res.UserId == nil {
			return nil, resultx.NewErrCode(resultx.USER_ID_INVALID)
		}

		var likeCount *uint64
		var collectEntryCount *uint64
		var collectEntryStatus int32
		var collectEntryItems []*types.KbEntryInfo
		var postPhotoCount *uint64
		var photoNewStatus int32
		var photoPostItems []*types.PhotoPostInfo
		var orderCount *uint64
		var orderNewStatus bool
		var reviewCount *uint64
		var reviewNewStatus int32
		var askedQuestionCount *uint64
		var askedQuestionNewStatus int32
		var answeredQuestionCount *uint64
		var answeredQuestionNewStatus int32
		var wantEntryCount *uint64
		var ownEntryCount *uint64
		var ownEntryStatus int32
		var ownEntryItems []*types.KbEntryInfo
		var couponCount *uint64
		var expiringCouponCount *uint64
		if len(res.UserMeta) > 0 {
			for _, v := range res.UserMeta {
				if v.Key == nil || v.Value == nil {
					continue
				}

				key := strings.TrimSpace(*v.Key)
				val := strings.TrimSpace(*v.Value)
				if len(key) == 0 || len(val) == 0 {
					continue
				}

				switch key {
				case "likeCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						likeCount = pointy.GetPointer(uint64(i))
					}
				case "collectEntryCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						collectEntryCount = pointy.GetPointer(uint64(i))
					}
				case "collectEntryStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						collectEntryStatus = int32(i)
					}
				case "collectEntryItems":
					if err := json.Unmarshal([]byte(val), &collectEntryItems); err != nil {
						logx.Errorw("GetUserProfile collectEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
					}
				case "postPhotoCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						postPhotoCount = pointy.GetPointer(uint64(i))
					}
				case "photoNewStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						photoNewStatus = int32(i)
					}
				case "photoPostItems":
					if err := json.Unmarshal([]byte(val), &photoPostItems); err != nil {
						logx.Errorw("GetUserProfile photoPostItems json.Unmarshal err", logx.Field("detail", err.Error()))
					}
				case "orderCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						orderCount = pointy.GetPointer(uint64(i))
					}
				case "orderNewStatus":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil && i > 0 {
						orderNewStatus = true
					}
				case "reviewCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						reviewCount = pointy.GetPointer(uint64(i))
					}
				case "reviewNewStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						reviewNewStatus = int32(i)
					}
				case "askedQuestionCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						askedQuestionCount = pointy.GetPointer(uint64(i))
					}
				case "askedQuestionNewStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						askedQuestionNewStatus = int32(i)
					}
				case "answeredQuestionCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						answeredQuestionCount = pointy.GetPointer(uint64(i))
					}
				case "answeredQuestionNewStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						answeredQuestionNewStatus = int32(i)
					}
				case "wantEntryCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						wantEntryCount = pointy.GetPointer(uint64(i))
					}
				case "ownEntryCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						ownEntryCount = pointy.GetPointer(uint64(i))
					}
				case "ownEntryStatus":
					if i, err := strconv.ParseInt(val, 10, 32); err == nil {
						ownEntryStatus = int32(i)
					}
				case "ownEntryItems":
					if err := json.Unmarshal([]byte(val), &ownEntryItems); err != nil {
						logx.Errorw("GetUserProfile collectEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
					}
				case "couponCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						couponCount = pointy.GetPointer(uint64(i))
					}
				case "expiringCouponCount":
					if i, err := strconv.ParseInt(val, 10, 64); err == nil {
						expiringCouponCount = pointy.GetPointer(uint64(i))
					}
				}
			}
		}

		var cacheType uint32
		if reviewNewStatus == -1 { // -1 意味着 user rpc 还没有更新缓存，本次从 forum rpc 查询缓存，并通知 user rpc 更新缓存。所以也要显示红点，效果同1。
			cacheType += cachex.ForumNewReview
		}
		if photoNewStatus == -1 {
			cacheType += cachex.ForumNewPhotoPost
		}
		if askedQuestionNewStatus == -1 {
			cacheType += cachex.ForumNewAskedQuestion
		}
		if answeredQuestionNewStatus == -1 {
			cacheType += cachex.ForumNewAnsweredQuestion
		}
		if collectEntryStatus == -1 {
			cacheType += cachex.ForumNewCollectEntry
		}
		if cacheType > 0 {
			ret, err := l.svcCtx.ForumRpc.RefreshCache(l.ctx, &forumclient.RefreshCacheReq{
				UserId:     pointy.GetPointer(id),
				Type:       pointy.GetPointer(cacheType),
				PlatformId: pointy.GetPointer(uint32(globalkey.ThirdPartyPlatformWechatMini)),
			})
			if err != nil {
				logx.Errorw("GetUserProfile RefreshCache err", logx.Field("detail", err.Error()))
				// logrus.Info(fmt.Sprintf("GetUserProfile RefreshCache err: %+v", err))
			} else if len(ret.Meta) > 0 {
				for _, v := range ret.Meta {
					if v.Key == nil || v.Value == nil {
						continue
					}

					key := strings.TrimSpace(*v.Key)
					val := strings.TrimSpace(*v.Value)
					if len(key) == 0 || len(val) == 0 {
						continue
					}

					switch key {
					case "collectEntryItems":
						var newCollectEntryItems []*types.KbEntryInfo
						if err := json.Unmarshal([]byte(val), &newCollectEntryItems); err != nil {
							logx.Errorw("GetUserProfile newCollectEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							collectEntryItems = newCollectEntryItems[:]
						}
					case "photoPostItems":
						var newPhotoPostItems []*types.PhotoPostInfo
						if err := json.Unmarshal([]byte(val), &newPhotoPostItems); err != nil {
							logx.Errorw("GetUserProfile photoPostItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							photoPostItems = newPhotoPostItems[:]
						}
					case "ownEntryItems":
						var newOwnEntryItems []*types.KbEntryInfo
						if err := json.Unmarshal([]byte(val), &newOwnEntryItems); err != nil {
							logx.Errorw("GetUserProfile newOwnEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							ownEntryItems = newOwnEntryItems[:]
						}
					}
				}
			}
		}
		if ownEntryStatus == -1 {
			ret, err := l.svcCtx.BlogRpc.RefreshCache(l.ctx, &blogclient.RefreshCacheReq{
				UserId:     pointy.GetPointer(id),
				Type:       pointy.GetPointer(cachex.ForumNewOwnEntry),
				PlatformId: pointy.GetPointer(uint32(globalkey.ThirdPartyPlatformWechatMini)),
			})
			if err != nil {
				logx.Errorw("GetUserProfile RefreshCache err", logx.Field("detail", err.Error()))
				// logrus.Info(fmt.Sprintf("GetUserProfile RefreshCache err: %+v", err))
			} else if len(ret.Meta) > 0 {
				for _, v := range ret.Meta {
					if v.Key == nil || v.Value == nil {
						continue
					}

					key := strings.TrimSpace(*v.Key)
					val := strings.TrimSpace(*v.Value)
					if len(key) == 0 || len(val) == 0 {
						continue
					}

					switch key {
					case "collectEntryItems":
						var newCollectEntryItems []*types.KbEntryInfo
						if err := json.Unmarshal([]byte(val), &newCollectEntryItems); err != nil {
							logx.Errorw("GetUserProfile newCollectEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							collectEntryItems = newCollectEntryItems[:]
						}
					case "photoPostItems":
						var newPhotoPostItems []*types.PhotoPostInfo
						if err := json.Unmarshal([]byte(val), &newPhotoPostItems); err != nil {
							logx.Errorw("GetUserProfile photoPostItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							photoPostItems = newPhotoPostItems[:]
						}
					case "ownEntryItems":
						var newOwnEntryItems []*types.KbEntryInfo
						if err := json.Unmarshal([]byte(val), &newOwnEntryItems); err != nil {
							logx.Errorw("GetUserProfile newOwnEntryItems json.Unmarshal err", logx.Field("detail", err.Error()))
						} else {
							ownEntryItems = newOwnEntryItems[:]
						}
					}
				}
			}
		}

		return &types.UserProfileResp{
			UserId: res.UserId,

			LikeCount:                 likeCount,
			CollectEntryCount:         collectEntryCount,
			CollectEntryItems:         collectEntryItems,
			PostPhotoCount:            postPhotoCount,
			PhotoNewStatus:            photoNewStatus != 0,
			PhotoPostItems:            photoPostItems,
			OrderCount:                orderCount,
			OrderNewStatus:            orderNewStatus,
			ReviewCount:               reviewCount,
			ReviewNewStatus:           reviewNewStatus != 0,
			AskedQuestionCount:        askedQuestionCount,
			AskedQuestionNewStatus:    askedQuestionNewStatus != 0,
			AnsweredQuestionCount:     answeredQuestionCount,
			AnsweredQuestionNewStatus: answeredQuestionNewStatus != 0,
			CouponCount:               couponCount,
			ExpiringCouponCount:       expiringCouponCount,

			WantEntryCount: wantEntryCount,
			OwnEntryCount:  ownEntryCount,
			OwnEntryItems:  ownEntryItems,
		}, nil
	}

	return &types.UserProfileResp{}, nil
}
